package org.mapdroid.maps.gmaps.overlay;

import org.mapdroid.R;
import org.mapdroid.maps.gmaps.MdMapActivity;
import org.mapdroid.maps.gmaps.MdMapView;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Paint.Style;
import android.location.Location;
import android.os.Vibrator;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.GestureDetector.OnGestureListener;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class MdMarkerRangeOverlay extends Overlay implements OnGestureListener, GestureDetector.OnDoubleTapListener{
	public static final float DEFAULT_RANGE_E6 = 500;
	public static final String CURRENT_RANGE_VALUE = "CURRENT_RANGE_VALUE";
	
	private MdMapView mapView;
	private Paint paint;
	private float rangeMeters;
	private GeoPoint pos;
	private Context context;
	private GestureDetector gestureDetector;
	private boolean isInEditingMode;
	private int Tx, Ty;
	private Vibrator vibrator;
	
	public MdMarkerRangeOverlay(Context context, MdMapView mapView, float rangeMeters){
		super();
		this.context = context;
		this.mapView = mapView;
		this.rangeMeters = 0;
		paint = new Paint();
		paint.setARGB(0, 255, 100, 100);
		paint.setAntiAlias(true);
		
		this.gestureDetector = new GestureDetector(this.context, this);
		
		this.isInEditingMode = false;
		
		WindowManager window = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		this.Ty = window.getDefaultDisplay().getHeight() / 2;
		this.Tx = window.getDefaultDisplay().getWidth() / 2;
		
		this.vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
	}	
	
	public void setPosition(GeoPoint pos){
		this.pos = pos;
		/*if(pos!=null && rangeMeters==0){
			Location a = new Location(LocationManager.GPS_PROVIDER);
			Location b = new Location(LocationManager.GPS_PROVIDER);
			a.setLatitude(pos.getLatitudeE6()/1E6);
			a.setLongitude(pos.getLongitudeE6()/1E6);
			b.setLatitude(pos.getLatitudeE6()/1E6+this.rangeE6/1E6);
			b.setLongitude(pos.getLongitudeE6()/1E6);
			this.rangeMeters = a.distanceTo(b);
		}
		if(pos!=null && rangeMeters>0){
			this.rangeMeters = rangeMeters;
		}*/
	}
	
	public void setRange(float range){
		this.rangeMeters = range;
	}
	
	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow){
		//super.draw(canvas, mapView, shadow);
		if(mapView==null || pos==null)
			return;
		
		Projection proj = mapView.getProjection();
		Point point = new Point();
		proj.toPixels(pos, point);
		
		float radius = proj.metersToEquatorPixels(rangeMeters);
		
		paint.setAlpha(50);
		paint.setStyle(Style.FILL);
		paint.setStrokeWidth(2.0f);
		canvas.drawCircle(point.x, point.y, radius, paint);
		
		paint.setAlpha(150);
		paint.setStyle(Style.STROKE);
		canvas.drawCircle(point.x, point.y, radius, paint);
	}


	@Override
	public boolean onTouchEvent(MotionEvent event, MapView mapView) {
		// TODO Auto-generated method stub
		super.onTouchEvent(event, mapView);
		if(!isInEditingMode){
			if(hitTest(mapView, event.getX(), event.getY())){
				gestureDetector.onTouchEvent(event);
				this.mapView.hasEventHandled(true);
				return false;
			}
		}
		else{
			gestureDetector.onTouchEvent(event);
			this.mapView.hasEventHandled(true);
			//mapView.getOverlays().set(MdMapView.RANGE_OVERLAY_INDEX, this);
			return true;
		}
		this.mapView.hasEventHandled(false);
		return false;
	}
	
	private boolean hitTest(MapView mapView, float x, float y) {
		// TODO Auto-generated method stub
		Projection proj = mapView.getProjection();
		float radius = proj.metersToEquatorPixels(this.rangeMeters);
		Point point = new Point();
		proj.toPixels(pos, point); 
		
		if(	x>point.x-radius	&&	x<point.x+radius &&
			y>point.y-radius	&&	y<point.y+radius)
			return true;
		
		return false;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		if(isInEditingMode){
			double radiusB = Math.sqrt(Math.pow(e2.getX()-Tx, 2) + Math.pow(e2.getY()-Ty, 2));
			double radiusA = Math.sqrt(Math.pow(e1.getX()-Tx, 2) + Math.pow(e1.getY()-Ty, 2));
			int sign = (radiusB - radiusA > 0) ? 1 : -1;
			
			GeoPoint gpStart = mapView.getProjection().fromPixels((int)e1.getX(), (int)e1.getY());
			GeoPoint gpEnd	 = mapView.getProjection().fromPixels((int)e2.getX(), (int)e2.getY());
			float results[] = new float[4];
			Location.distanceBetween(	gpStart.getLatitudeE6()/1E6, 
										gpStart.getLongitudeE6()/1E6, 
										gpEnd.getLatitudeE6()/1E6,
										gpEnd.getLongitudeE6()/1E6,
										results);
			double meters = results[0];
			
			this.rangeMeters = (float) (this.rangeMeters + sign*meters);
			MdMapActivity.setServiceRange(rangeMeters);
			return true;
		}
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		/*if(isInEditingMode){
			double radiusB = Math.sqrt(Math.pow(e2.getX()-Tx, 2) + Math.pow(e2.getY()-Ty, 2));
			double radiusA = Math.sqrt(Math.pow(e1.getX()-Tx, 2) + Math.pow(e1.getY()-Ty, 2));
			int sign = (radiusB - radiusA > 0) ? 1 : -1;
			
			GeoPoint gpStart = mapView.getProjection().fromPixels((int)e1.getX(), (int)e1.getY());
			GeoPoint gpEnd	 = mapView.getProjection().fromPixels((int)e2.getX(), (int)e2.getY());
			float results[] = new float[4];
			Location.distanceBetween(	gpStart.getLatitudeE6()/1E6, 
										gpStart.getLongitudeE6()/1E6, 
										gpEnd.getLatitudeE6()/1E6,
										gpEnd.getLongitudeE6()/1E6,
										results);
			double meters = results[0];
			
			this.rangeMeters = (float) (this.rangeMeters + sign*meters);
			MdMapActivity.setServiceRange(rangeMeters);
			return true;
		}*/
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onDoubleTap(MotionEvent e) {
		// TODO Auto-generated method stub
		vibrator.vibrate(75);
		
		if(!isInEditingMode){
			paint.setARGB(0, 100, 255, 100);
			isInEditingMode = true;
		}
		else{
			paint.setARGB(0, 255, 100, 100);
			isInEditingMode = false;
		}
		return true;
	}

	@Override
	public boolean onDoubleTapEvent(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {
		// TODO Auto-generated method stub
		if(!isInEditingMode){
			vibrator.vibrate(75);
			Toast.makeText(context, context.getString(R.string.service_range_text) + " " + String.format("%.2f", this.rangeMeters) + " " + context.getString(R.string.meters_text), Toast.LENGTH_SHORT).show();
		}
		return true;
	}
}
